// This file is part of Keepass2Android, Copyright 2025 Philipp Crocoll.
//
//   Keepass2Android is free software: you can redistribute it and/or modify
//   it under the terms of the GNU General Public License as published by
//   the Free Software Foundation, either version 3 of the License, or
//   (at your option) any later version.
//
//   Keepass2Android is distributed in the hope that it will be useful,
//   but WITHOUT ANY WARRANTY; without even the implied warranty of
//   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//   GNU General Public License for more details.
//
//   You should have received a copy of the GNU General Public License
//   along with Keepass2Android.  If not, see <http://www.gnu.org/licenses/>.

using System;
using System.Collections.Generic;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using Android.App;
using System.IO;
using Android.Content;
using Android.OS;
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using keepass2android.Io;
using KeePassLib.Interfaces;
#if !NoNet && !EXCLUDE_JAVAFILESTORAGE
using Keepass2android.Javafilestorage;
#endif 

namespace keepass2android
{
  public interface ICertificateValidationHandler
  {
    /// <summary>
    /// Handles a failed certificate validation. Returns true if the users wants to continue, false otherwise.
    /// see http://msdn.microsoft.com/en-us/library/system.net.icertificatepolicy(v=vs.110).aspx
    /// </summary>
    //bool OnServerCertificateError(int certificateProblem);

    RemoteCertificateValidationCallback CertificateValidationCallback { get; }

  }


  public enum MessageSeverity
  {
    Info,
    Warning,
    Error
  }

  /// <summary>
  /// Interface through which Activities and the logic layer can access some app specific functionalities and Application static data
  /// </summary>
  /// This also contains methods which are UI specific and should be replacable for testing.
  public interface IKp2aApp : ICertificateValidationHandler, IActiveContextProvider
  {
    /// <summary>
    /// Locks all currently open databases, quicklocking if available (unless false is passed for allowQuickUnlock)
    /// </summary>
    void Lock(bool allowQuickUnlock, bool lockWasTriggeredByTimeout);


    /// <summary>
    /// Loads the specified data as the currently open database, as unlocked.
    /// </summary>
    Database LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey,
        IKp2aStatusLogger statusLogger, IDatabaseFormat databaseFormat, bool makeCurrent,
        IDatabaseModificationWatcher modificationWatcher);


    HashSet<PwGroup> DirtyGroups { get; }

    void MarkAllGroupsAsDirty();

    /// <summary>
    /// Returns the current database
    /// </summary>
    Database CurrentDb { get; }

    IEnumerable<Database> OpenDatabases { get; }
    void CloseDatabase(Database db);

    Database FindDatabaseForElement(IStructureItem element);

    /// <summary>
    /// Tell the app that the file from ioc was opened with keyfile.
    /// </summary>
    void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile, bool updateTimestamp, string displayName = "");

    /// <summary>
    /// Creates a new database and returns it
    /// </summary>
    Database CreateNewDatabase(bool makeCurrent);

    /// <summary>
    /// Returns the user-displayable string identified by stringKey
    /// </summary>
    string GetResourceString(UiStringKey stringKey);

    /// <summary>
    /// Returns the value from the preferences corresponding to key
    /// </summary>
    bool GetBooleanPreference(PreferenceKey key);

    /// <summary>
    /// Asks the user the question "messageKey" with the options Yes/No/Cancel, calls the handler corresponding to the answer.
    /// </summary>
    void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
                        EventHandler<DialogClickEventArgs> yesHandler,
                        EventHandler<DialogClickEventArgs> noHandler,
                        EventHandler<DialogClickEventArgs> cancelHandler,
                        string messageSuffix = "");

    /// <summary>
    /// Asks the user the question "messageKey" with the options Yes/No/Cancel, but the yes/no strings can be selected freely, calls the handler corresponding to the answer.
    /// </summary>
    void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
                        UiStringKey yesString, UiStringKey noString,
                        EventHandler<DialogClickEventArgs> yesHandler,
                        EventHandler<DialogClickEventArgs> noHandler,
                        EventHandler<DialogClickEventArgs> cancelHandler,
                        string messageSuffix = "");

    void ShowMessage(Context ctx, int resourceId, MessageSeverity severity);
    void ShowMessage(Context ctx, string text, MessageSeverity severity);

    /// <summary>
    /// Returns a Handler object which can run tasks on the UI thread
    /// </summary>
    Handler UiThreadHandler { get; }

    IProgressDialog CreateProgressDialog(Context ctx);

    /// <summary>
    /// returns the file storage for the given ioc. might be a caching file storage
    /// </summary>
    IFileStorage GetFileStorage(IOConnectionInfo iocInfo);

    /// <summary>
    /// returns the file storage for the given ioc. if allowCache=false, no cached file storage is returned
    /// </summary>
    IFileStorage GetFileStorage(IOConnectionInfo iocInfo, bool allowCache);

    void TriggerReload(Context context, Action<bool> actionOnResult /*if not null, called when the user selected yes (true) or no (false)*/);


    bool CheckForDuplicateUuids { get; }
#if !NoNet && !EXCLUDE_JAVAFILESTORAGE
    ICertificateErrorHandler CertificateErrorHandler { get; }
#endif
    int WebDavChunkedUploadSize
    {
      get;
    }

    bool SyncInBackgroundPreference { get; set; }
    void StartBackgroundSyncService();

    ReaderWriterLockSlim DatabasesBackgroundModificationLock { get; }
    bool CancelBackgroundOperations();

    /// <summary>
    /// Registers an action that should be executed when the context instance with the given id has been resumed.
    /// </summary>
    void RegisterPendingActionForContextInstance(int contextInstanceId, ActionOnOperationFinished actionToPerformWhenContextIsResumed);
  }
}